#region Copyright (c) 2006-2009 Widgetsphere LLC, All Rights Reserved
//--------------------------------------------------------------------- *
//                          Widgetsphere  LLC                           *
//             Copyright (c) 2006-2009 All Rights reserved              *
//                                                                      *
//                                                                      *
//This file and its contents are protected by United States and         *
//International copyright laws.  Unauthorized reproduction and/or       *
//distribution of all or any portion of the code contained herein       *
//is strictly prohibited and will result in severe civil and criminal   *
//penalties.  Any violations of this copyright will be prosecuted       *
//to the fullest extent possible under law.                             *
//                                                                      *
//THE SOURCE CODE CONTAINED HEREIN AND IN RELATED FILES IS PROVIDED     *
//TO THE REGISTERED DEVELOPER FOR THE PURPOSES OF EDUCATION AND         *
//TROUBLESHOOTING. UNDER NO CIRCUMSTANCES MAY ANY PORTION OF THE SOURCE *
//CODE BE DISTRIBUTED, DISCLOSED OR OTHERWISE MADE AVAILABLE TO ANY     *
//THIRD PARTY WITHOUT THE EXPRESS WRITTEN CONSENT OF WIDGETSPHERE LLC   *
//                                                                      *
//UNDER NO CIRCUMSTANCES MAY THE SOURCE CODE BE USED IN WHOLE OR IN     *
//PART, AS THE BASIS FOR CREATING A PRODUCT THAT PROVIDES THE SAME, OR  *
//SUBSTANTIALLY THE SAME, FUNCTIONALITY AS ANY WIDGETSPHERE PRODUCT.    *
//                                                                      *
//THE REGISTERED DEVELOPER ACKNOWLEDGES THAT THIS SOURCE CODE           *
//CONTAINS VALUABLE AND PROPRIETARY TRADE SECRETS OF WIDGETSPHERE,      *
//INC.  THE REGISTERED DEVELOPER AGREES TO EXPEND EVERY EFFORT TO       *
//INSURE ITS CONFIDENTIALITY.                                           *
//                                                                      *
//THE END USER LICENSE AGREEMENT (EULA) ACCOMPANYING THE PRODUCT        *
//PERMITS THE REGISTERED DEVELOPER TO REDISTRIBUTE THE PRODUCT IN       *
//EXECUTABLE FORM ONLY IN SUPPORT OF APPLICATIONS WRITTEN USING         *
//THE PRODUCT.  IT DOES NOT PROVIDE ANY RIGHTS REGARDING THE            *
//SOURCE CODE CONTAINED HEREIN.                                         *
//                                                                      *
//THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE.              *
//--------------------------------------------------------------------- *
#endregion
using System;
using System.Xml;
using System.ComponentModel;
using Widgetsphere.Generator.Common.GeneratorFramework;
using Widgetsphere.Generator.Common.Util;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing.Design;

namespace Widgetsphere.Generator.Models
{
  public class ModelRoot : BaseModelObject
	{
		#region Member Variables

		protected internal const string _def_version = "0.0.0.0";
		protected const bool _def_useUTCTime = false;

		protected Database _database = null;
		protected UserInterface _userInterface = null;
		protected string _companyName = "";
		protected string _companyAbbreviation = "";
		protected string _copyright = "";
		protected string _projectName = "";
		protected bool _useUTCTime = _def_useUTCTime;
		protected string _version = _def_version;
		protected IGenerator _generatorProject = null;
		private DateTime _createdDate = DateTime.Now;
		private VersionHistoryCollection _versionHistoryList = new VersionHistoryCollection();

		#endregion 

    #region Constructor

    public ModelRoot(IModelObject root)
      : base(root)
    {
      _database = new Database(this);
      _userInterface = new UserInterface(this);
    }

    #endregion 

		#region Property Implementations

		[Browsable(false)]
		public IGenerator GeneratorProject
		{
			get { return _generatorProject; }
			set { _generatorProject = value; }
		}

		[
		Browsable(true),
    Description("Specifies the name of the generated assembly."),
		Category("Data"),
		]
		public string ProjectName
		{
      get { return _projectName; }
			set
			{
				_projectName = value;
				this.OnPropertyChanged(this, new PropertyChangedEventArgs("ProjectName"));
			}
		}

		[
		Browsable(true),
    Description("Specifies whether UTC or local time is used for the created and modified audits."),
		Category("Data"),
		DefaultValue(_def_useUTCTime),
		]
		public bool UseUTCTime
		{
			get { return _useUTCTime; }
			set
			{
				_useUTCTime = value;
				this.OnPropertyChanged(this, new PropertyChangedEventArgs("UseUTCTime"));
			}
		}		

		[
		Browsable(true),
		Description("Specifies the version number of the generated assembly."),
		Category("Data"),
		TypeConverter(typeof(Widgetsphere.Generator.Design.Converters.VersionConverter)),
		]
		public string Version
		{
      get { return _version; }
      set
      {
				if (_version != value)
				{
					_version = value;
					this.OnPropertyChanged(this, new PropertyChangedEventArgs("Version"));
					this.VersionHistoryList.Add(new VersionHistory(_version));
				}
      }
		}

    [Browsable(false)]
    public UserInterface UserInterface
    {
      get { return _userInterface; }
      set { _userInterface = value; }
    }

		[
		Browsable(true),
		Description("Specifies the company name that will be used to build namespaces."),
		Category("Data"),
		]
		public string CompanyName
		{
      get { return _companyName; }
			set
      {
				_companyName = value;
				this.OnPropertyChanged(this, new PropertyChangedEventArgs("CompanyName"));
			}
		}

		[
		Browsable(true),
		Description("Specifies a short name for the company."),
		Category("Data"),
		]
		public string CompanyAbbreviation
		{
			get { return _companyAbbreviation; }
			set
			{
				_companyAbbreviation = value;
				this.OnPropertyChanged(this, new PropertyChangedEventArgs("CompanyAbbreviation"));
			}
		}
		
		[Browsable(false)]
    public Database Database
    {
      get { return _database; }
      set { _database = value; }
    }

		[Browsable(true)]
		[Category("Data")]
		[Description("The date that this object was created.")]
		[ReadOnlyAttribute(true)]
		public DateTime CreatedDate
		{
			get { return _createdDate; }
		}


		[Browsable(true)]
		[Category("Design")]
		[ReadOnlyAttribute(true)]
		[TypeConverter(typeof(Widgetsphere.Generator.Design.Converters.VersionHistoryCollectionConverter))]
		[Editor(typeof(Widgetsphere.Generator.Design.Editors.VersionHistoryCollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
		public VersionHistoryCollection VersionHistoryList
		{
			get { return _versionHistoryList; }
		}

		[
		Browsable(true),
		Description("Determines copyright to add to each file."),
		Category("Data"),
		Editor(typeof(Widgetsphere.Generator.Design.Editors.TextEditor), typeof(UITypeEditor)),
		]
		public string Copyright
		{
			get { return _copyright; }
			set
			{
				_copyright = value;
				this.OnPropertyChanged(this, new PropertyChangedEventArgs("Copyright"));
			}
		}

		#endregion

		#region IXMLable

		public override void XmlAppend(XmlNode node)
		{
      try
      {
        XmlDocument oDoc = node.OwnerDocument;

        XmlAttribute keyNode = oDoc.CreateAttribute("key");
        keyNode.Value = this.Key.ToString();
        node.Attributes.Append(keyNode);

        XmlAttribute projectName = oDoc.CreateAttribute("projectName");
        projectName.Value = this.ProjectName;
        node.Attributes.Append(projectName);

				XmlAttribute useUTCTime = oDoc.CreateAttribute("useUTCTime");
				useUTCTime.Value = this.UseUTCTime.ToString();
				node.Attributes.Append(useUTCTime);

        XmlAttribute version = oDoc.CreateAttribute("version");
        version.Value = this.Version;
        node.Attributes.Append(version);

        XmlNode userInterfaceNode = oDoc.CreateElement("userInterface");
        this.UserInterface.XmlAppend(userInterfaceNode);
        node.AppendChild(userInterfaceNode);

        XmlAttribute companyName = oDoc.CreateAttribute("companyName");
        companyName.Value = this.CompanyName;
        node.Attributes.Append(companyName);

				XmlAttribute companyAbbreviation = oDoc.CreateAttribute("companyAbbreviation");
				companyAbbreviation.Value = this.CompanyAbbreviation;
				node.Attributes.Append(companyAbbreviation);

				XmlNode copyright = oDoc.CreateNode(XmlNodeType.Element, "copyright", "");
				XmlCDataSection copyright2 = oDoc.CreateCDataSection("copyright");				
				copyright2.Value = this.Copyright;
				copyright.AppendChild(copyright2);
				node.AppendChild(copyright);

        XmlNode databaseNode = oDoc.CreateElement("database");
        this.Database.XmlAppend(databaseNode);
        node.AppendChild(databaseNode);

				XmlAttribute created = oDoc.CreateAttribute("createdDate");
				created.Value = _createdDate.ToString("yyyy-MM-dd HH:mm:ss");
				node.Attributes.Append(created);

				XmlNode versionHistoryListNode = oDoc.CreateElement("versionHistoryList");
				node.AppendChild(versionHistoryListNode);
				_versionHistoryList.XmlAppend(versionHistoryListNode);

      }
      catch(Exception ex)
      {
        throw;
      }
		}

		public override void XmlLoad(XmlNode node)
		{
			_key = XmlHelper.GetAttributeValue(node, "key", _key);
			this.ProjectName = node.Attributes["projectName"].Value;
			_version = node.Attributes["version"].Value;
			this.UseUTCTime = bool.Parse(XmlHelper.GetAttributeValue(node, "useUTCTime", this.UseUTCTime.ToString()));

			XmlNode uiNode = node.SelectSingleNode("userInterface");
			if (uiNode != null)
				this.UserInterface.XmlLoad(uiNode);

			this.CompanyName = node.Attributes["companyName"].Value;
			if (node.Attributes["companyAbbreviation"] != null)
			{
				this.CompanyAbbreviation = node.Attributes["companyAbbreviation"].Value;
			}

			XmlNode databaseNode = node.SelectSingleNode("database");
			if (databaseNode != null)
				this.Database.XmlLoad(databaseNode);

			_createdDate = DateTime.ParseExact(XmlHelper.GetAttributeValue(node, "createdDate", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), "yyyy-MM-dd HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);

			XmlNode copyrightNode = node.SelectSingleNode("copyright");
			if (copyrightNode != null)
				_copyright = copyrightNode.InnerText;

			XmlNode versionHistoryListNode = node.SelectSingleNode("versionHistoryList");
			if (versionHistoryListNode != null)
				_versionHistoryList.XmlLoad(versionHistoryListNode);

			this.Dirty = false;
		}

		#endregion

		#region private helper methods
		#endregion

		#region generation helper methods

    internal void CleanUp()
    {
      try
      {
        ArrayList delList = new ArrayList();

        //Remove orphaned columns
        foreach(Column column in this.Database.Columns)
        {
          if((column.ParentTableRef == null) || 
            (column.ParentTableRef.Object == null) || 
            (column.ParentTableRef == null) || 
            (column.ParentTableRef.Object == null))
          {
            delList.Add(column);
          }
        }

        foreach(Column column in delList)
          this.Database.Columns.Remove(column);

        //Remove orphaned relations
        delList = new ArrayList();
        foreach(Relation relation in this.Database.Relations)
        {
          if((relation.ParentTableRef == null) ||
            (relation.ParentTableRef.Object == null) ||
            (relation.ParentTableRef == null) ||
            (relation.ParentTableRef.Object == null))
          {
            delList.Add(relation);
          }
					else if (relation.FkColumns.Count == 0)
					{
						delList.Add(relation);
					}

        }

        foreach(Relation relation in delList)
          this.Database.Relations.Remove(relation);

      }
      catch(Exception ex)
      {
        throw;
      }
    }

		#endregion

    #region IModelObject Members

    [Browsable(false)]
    public IModelObject Root
    {
      get { return this; }
    }

    string _key = Guid.NewGuid().ToString();
    [Browsable(false)]
    public string Key
    {
      get { return _key; }
    }

    #endregion
  
  }
}
